#include "scene.h"
#include "collision.h"
#include "geometry.h"
#include <iostream>

Scene::Scene()
{

}

Scene::~Scene()
{

}

void Scene::loadAttributes(std::istream &inData)
{
  std::string command, target;
  while (inData >> command)
  {
    if (command=="material")
    {
      m_loadMaterial(inData);
    }
    else if (command=="light")
    {
      m_loadLight(inData);
    }
    else if (command=="geom")
    {
      m_loadGeometry(inData);
    }
  }
}

Collision Scene::intersectScene(Ray r)
{
  Collision firstCollision;
  firstCollision.isValid = false;
  if (r.recursionLevel > 10)
  {
    return firstCollision;
  }
  for (GeometryIterator i = m_geometry.begin(); i != m_geometry.end(); i++)
  {
    if ((*i) != r.parent)
    {
      Collision c = (*i)->intersect(r);
      if (c.isValid && (c.distance < firstCollision.distance ||
          !firstCollision.isValid))
      {
        firstCollision = c;
      }
    }
  }
  return firstCollision;
}
void Scene::cast(Ray r, Color &targetColor)
{
  Collision c = intersectScene(r);
  if (c.isValid)
  {
    c.material->computeColor(c, targetColor);
  }
  else
  {  
    targetColor.r = targetColor.g = targetColor.b = 0;
  }
}

void Scene::m_loadMaterial(std::istream &inData)
{
  std::string name, target;
  inData >> name >> target;
  Material *tmpMaterial = 0;
  if (target=="solid")
  {
    tmpMaterial = new SolidMaterial(this);
  }
  else if (target=="texture")
  {
    tmpMaterial = new TextureMaterial(this);
  }
  tmpMaterial->loadAttributes(inData);
  Material::cache(name, tmpMaterial); 
}

void Scene::m_loadLight(std::istream &inData)
{
  std::string target;
  inData >> target;
  Light *tmpLight = 0;
  if (target=="point")
  {
    tmpLight = new PointLight(this);
  }
  tmpLight->loadAttributes(inData);
  Light::cache(tmpLight); 
}

void Scene::m_loadGeometry(std::istream &inData)
{
  std::string target;
  inData >> target;
  Geometry *tmpGeom = 0;
  if (target=="sphere")
  {
    tmpGeom = new Sphere(this);
  }
  tmpGeom->loadAttributes(inData);
  m_geometry.push_back(tmpGeom);
}
